home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 June: Reference Library / Dev.CD Jun 99 RL Disk 1.toast / Technical Documentation / Develop / Additional Articles / Developing Symbiotic Apps / Symbiotic Samples / Symbiotic server source / flexibled & simpled / status.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-04  |  7.2 KB  |  266 lines  |  [TEXT/CWIE]

  1. /* status.c -- routines for extracting status information from the machine
  2.  *
  3.  * %W%
  4.  *
  5.  * Authors: Chris Jalbert
  6.  * Copyright 1996 Apple Computer, Inc.
  7.  * All Rights Reserved.
  8.  *
  9.  * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF APPLE COMPUTER, INC.
  10.  * The copyright notice above does not evidence any actual or
  11.  * intended publication of such source code.
  12.  *
  13.  * History:
  14.  * 8/27/96 Chris Jalbert
  15.  *    Initial check in of new sample.
  16.  * 10/9/96 Chris Jalbert
  17.  *    Changed AIX code from using pipes to accessing services directly.
  18.  */
  19.  
  20. #if defined(_AIX) && !defined(SIMPLIFIED)
  21. # ifdef _ALL_SOURCE
  22. #  include <sys/select.h>    /* required for fd_set and select() */
  23. # else
  24. #  define _ALL_SOURCE
  25. #  include <sys/select.h>    /* required for fd_set and select() */
  26. #  undef _ALL_SOURCE
  27. # endif /* _ALL_SOURCE */
  28. #endif    /* _AIX && SIMPLIFIED */
  29.  
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <signal.h>
  34. #include <time.h>
  35.  
  36. #include "tridentd.h"
  37. #include "debug.h"
  38.  
  39.  
  40. #ifdef _AIX
  41. #include <fcntl.h>        /* for unbuffered I/O */
  42. #include <utmp.h>        /* for utmp structs and macros */
  43. #include <nlist.h>        /* for struct nlist stuff used by _GetLoads() */
  44.  
  45. extern int knlist (struct nlist *, int, int) ;
  46.  
  47. #else    /* _AIX */
  48. #include <Timer.h>
  49.  
  50. #define _CountUsers()    1
  51. #define _GetLoads(dp)    dp[0] = dp[1] = dp[2] = 0.5
  52. #endif    /* _AIX */
  53.  
  54.  
  55. #define    MIN_S    (time_t)60        /* 1 min = MIN_S seconds... */
  56. #define    HOUR_S    (60 * MIN_S)
  57. #define    DAY_S    (24 * HOUR_S)
  58. #define    HOUR_M    (time_t)60        /* 1 hour = HOUR_M minutes */
  59. #define    DAY_M    (24 * HOUR_M)
  60.  
  61.  
  62. /******************************************************************************
  63.     ==>  Private Globals  <==
  64. ******************************************************************************/
  65. #ifdef _AIX
  66. static time_t    _BootTime ;
  67. static int        _UTmp ;
  68. #endif    /* _AIX */
  69.  
  70.  
  71. /******************************************************************************
  72.     ==>  Static Functions  <==
  73. ******************************************************************************/
  74. #ifdef _AIX
  75. /*-----------------------------------------------------------------------------
  76.     _CountUsers() walks the utmp file looking for user processes.
  77. -----------------------------------------------------------------------------*/
  78. static int _CountUsers (void)
  79.     {
  80.     register struct utmp    *spResult ;
  81.     register int            nUsers = 0 ;
  82.  
  83.     /* Look for user entries in the utmp file. */
  84.     while (NULL != (spResult = getutent ()))
  85.         if ((spResult->ut_type == USER_PROCESS)
  86.             && spResult->ut_user[0])
  87.             nUsers++ ;
  88.     /* Close the file so we start from scratch next time. */
  89.     endutent () ;
  90.     return nUsers ;
  91.     }
  92.  
  93. /*-----------------------------------------------------------------------------
  94.     _GetLoads() makes use of the kernel version of the standard Unix tool,
  95.     nlist, which searches name lists in executables. Although buffered I/O
  96.     does seem to work, the docs say only unbuffered I/O is valid.
  97. -----------------------------------------------------------------------------*/
  98. /*
  99.  * Must agree with SBITS in sys/prod/sched.c
  100.  */
  101. #define FSHIFT       16
  102. #define FSCALE        (1<<FSHIFT)
  103.  
  104. static void _GetLoads (
  105.     double                *dpArray)
  106.     {
  107.     static struct nlist    _nl = { "avenrun" } ;
  108.     unsigned long        runarray [3] = {0, 0, 0} ;
  109.     register int        kmem ;
  110.  
  111.     /* Find the "avenrun" entry in the kernel. */
  112.     if (-1 == (kmem = open ("/dev/kmem", O_RDONLY)))
  113.         return ;
  114.     knlist (&_nl, 1, sizeof (struct nlist)) ;
  115.     if (_nl.n_value == lseek (kmem, _nl.n_value, SEEK_SET))
  116.         read (kmem, runarray, sizeof (runarray)) ;
  117.     close (kmem) ;
  118.  
  119.     /* Convert the avenrun to doubles. */
  120.     *dpArray++ = ((double) runarray[0]) / FSCALE ;
  121.     *dpArray++ = ((double) runarray[1]) / FSCALE ;
  122.     *dpArray++ = ((double) runarray[2]) / FSCALE ;
  123.     }
  124. #endif    /* _AIX */
  125.  
  126.  
  127. /******************************************************************************
  128.     ==>  Global (Exported) Functions  <==
  129. ******************************************************************************/
  130.  
  131. int GetUptimeString (
  132.     char                *szpBuf,
  133.     long                lLength)
  134.     {
  135.     register char        *szpBuffer = szpBuf ;
  136.     register time_t        tUptime = time (NULL) ;
  137.     register long        lDays, lHours ;
  138.     register int        nUsers ;
  139.     time_t                tCurrent = tUptime ;
  140.     register struct tm    *tmCurrent = localtime (&tCurrent) ;
  141.     UnsignedWide        uptime ;
  142.     double                daLoads [3] ;
  143.  
  144. #ifdef _AIX
  145.     tUptime -= _BootTime ;
  146.     tUptime += 30 ;
  147.     tUptime /= MIN_S ;                /* Convert to minutes. */
  148. #else
  149.     Microseconds (&uptime) ;
  150.     tUptime = uptime.lo / 60000 ;    /* Convert to minutes. */
  151. #endif    /* _AIX */
  152.  
  153.     szpBuffer += strftime (szpBuffer, (lLength - (long) (szpBuffer - szpBuf)),
  154.                                 "%I:%M%p", tmCurrent) ;
  155.  
  156.     /* Convert uptime to readable format. */
  157.     lDays = tUptime / DAY_M ;
  158.     tUptime %= DAY_M ;
  159.     lHours = tUptime / HOUR_M ;
  160.     tUptime %= HOUR_M ;
  161.     if (lDays > 1)
  162.         szpBuffer += sprintf (szpBuffer, "  up %ld days,", lDays) ;
  163.     else if (lDays == 1)
  164.         szpBuffer += sprintf (szpBuffer, "  up 1 day,") ;
  165.     szpBuffer += sprintf (szpBuffer, "  %02d:%02d,", lHours, (long) tUptime) ;
  166.  
  167.     /* Count the number of users. */
  168.     nUsers = _CountUsers () ;
  169.     if (nUsers == 1)
  170.         szpBuffer += sprintf (szpBuffer, "  1 user") ;
  171.     else
  172.         szpBuffer += sprintf (szpBuffer, "  %d users", nUsers) ;
  173.  
  174.     /* Determine the load average. */
  175.     _GetLoads (daLoads) ;
  176.     sprintf (szpBuffer, ",  load average: %.2f, %.2f, %.2f\n",
  177.                         daLoads[0], daLoads[1], daLoads[2]) ;
  178.  
  179.     return noErr ;
  180.     }
  181.  
  182. #ifdef _AIX
  183. void InitApp (void)
  184.     {
  185.     struct utmp    sFilter, *spResult ;
  186.     ClientPtr    cspInherit ;
  187.  
  188.     /* Get bootime from utmp file. */
  189.     sFilter.ut_type = BOOT_TIME ;
  190.     if (NULL == (spResult = getutid (&sFilter)))
  191.         {
  192.         DBGM ("Couldn't find boot time!\n") ;
  193.         exit (1) ;
  194.         }
  195.  
  196.     _BootTime = spResult->ut_time ;
  197.     DBG ("Boot time was %lu.\n", _BootTime) ;
  198.     endutent () ;
  199.  
  200. #if SIMPLIFIED
  201.     /* Create the initial, inherited client connection. */
  202.     if (NULL != (cspInherit = NewClient (kUptimeType)))
  203.         ClientSetSession (cspInherit, 0) ;
  204. #else
  205.     /* Keep track of the utmp file and send updates only when necessary. */
  206.     if (-1 != (_UTmp = open (UTMP_FILE, O_RDONLY)))
  207.         lseek (_UTmp, 0, SEEK_END) ;
  208. #endif    /* !SIMPLIFIED */
  209.     }
  210.  
  211.  
  212. #if !SIMPLIFIED
  213. Boolean GetMySelectMask (
  214.     fd_set    *fdsMask)
  215.     {
  216.     if (WhoClients == NULL)
  217.         return false ;
  218.     FD_SET (_UTmp, fdsMask) ;
  219.     return true ;
  220.     }
  221.  
  222. /***
  223.  *** The AIX version of GetWhoString walks the utmp file looking for users.
  224.  *** It stuffs the buffer with the appropriate information.
  225.  ***/
  226. int GetWhoString (
  227.     char            *szpBuf,
  228.     long            lLength)
  229.     {
  230.     register char            *szpBuffer = szpBuf ;
  231.     register struct utmp    *spResult ;
  232.  
  233.     while (NULL != (spResult = getutent ()))
  234.         if ((spResult->ut_type == USER_PROCESS)
  235.             && spResult->ut_user[0])
  236.                 {
  237.                 struct tm    *tmLocal = localtime (&(spResult->ut_time)) ;
  238.                 szpBuffer += sprintf (szpBuffer, "%-8.8s    %-12.12s",
  239.                                         spResult->ut_user, spResult->ut_line) ;
  240.                 szpBuffer += strftime (szpBuffer,
  241.                                         (lLength - (long) (szpBuffer - szpBuf)),
  242.                                         "%b %e %H:%M    ", tmLocal) ;
  243.                 szpBuffer += sprintf (szpBuffer, "%s \n", spResult->ut_host) ;
  244.                 }
  245.     endutent () ;
  246.     }
  247. #endif    /* !SIMPLIFIED */
  248.  
  249. /***
  250.  *** The Mac version is extremely lazy: It just gets the default user name.
  251.  ***/
  252. #else    /* _AIX */
  253. int GetWhoString (
  254.     char            *szpBuffer,
  255.     long            lLength)
  256.     {
  257.     unsigned long    ulUser ;
  258.     Str32            sUser ;
  259.  
  260.     if (GetDefaultUser (&ulUser, sUser))
  261.         PStringLen (sUser) = 0 ;
  262.     strncpy (szpBuffer, PStringStr (sUser), PStringLen (sUser)) ;
  263.     return noErr ;
  264.     }
  265. #endif    /* _AIX */
  266.